package com.xhu.collegestudentrentalsystem.module.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.xhu.collegestudentrentalsystem.module.user.dao.HouseDAO;
import com.xhu.collegestudentrentalsystem.module.user.dao.HouseOrderDAO;
import com.xhu.collegestudentrentalsystem.module.user.dao.UserDAO;
import com.xhu.collegestudentrentalsystem.module.user.entity.House;
import com.xhu.collegestudentrentalsystem.module.user.entity.HouseOrder;
import com.xhu.collegestudentrentalsystem.module.user.entity.Page;
import com.xhu.collegestudentrentalsystem.module.user.entity.User;
import com.xhu.collegestudentrentalsystem.module.user.service.IOrderService;
import com.xhu.collegestudentrentalsystem.util.constant.EntityProperty;
import com.xhu.collegestudentrentalsystem.util.constant.StatusMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author zhu huilin
 * @date 2023/3/13 15:48
 */
@Service
public class OrderServiceImpl implements IOrderService {

    @Autowired
    private HouseOrderDAO houseOrderDAO;

    @Autowired
    private HouseDAO houseDAO;

    @Autowired
    private UserDAO userDAO;

    /**
     * 查询用户在此时间段是否已经有订单了
     */
    @Override
    public Boolean isCreatedOrder(Date startDate, Date endDate, Long houseId, Long userId) {
        List<HouseOrder> orders = houseOrderDAO.selectList(new QueryWrapper<HouseOrder>()
                .eq(EntityProperty.order.HOUSE_ID, houseId)
                .eq(EntityProperty.order.CUSTOMER_USER_ID, userId));

        if(!orders.isEmpty()) {
            for (HouseOrder order : orders) {
                if (startDate.before(order.getEndDate()) && endDate.after(order.getEndDate())) {
                    return true;
                }else if(startDate.before(order.getStartDate()) && endDate.after(order.getStartDate())){
                    return true;
                }else if(startDate.after(order.getStartDate()) && endDate.before(order.getEndDate())){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 生成一个订单信息
     */
    @Override
    public HouseOrder createOrder(Date startDate, Date endDate, Long houseId, Long userId) {
        HouseOrder houseOrder = new HouseOrder();
        // 填充数据
        houseOrder.setCreateTime(new Date());
        houseOrder.setCustomerUserId(userId);

        House house = houseDAO.selectOne(new QueryWrapper<House>().eq(EntityProperty.ID, houseId));
        houseOrder.setOwnerUserId(house.getUserId());
        houseOrder.setHouseId(house.getId());
        houseOrder.setStatus(StatusMsg.orderStatus.WAIT_SIGN);
        houseOrder.setMonthRent(house.getMonthRent());
        int day =(int) ((endDate.getTime() - startDate.getTime())/1000/60/60/24);
        houseOrder.setDayNum(day);
        // 一月30天，按照天数计算总金额
        houseOrder.setTotalAmount(house.getMonthRent()/30 * day);
        houseOrder.setStartDate(startDate);
        houseOrder.setEndDate(endDate);

        // 插入数据到订单表
        int result = houseOrderDAO.insert(houseOrder);
        if(result > 0) {
            return houseOrder;
        }
        return new HouseOrder();
    }

    /**
     * 根据id查询一条订单记录
     */
    @Override
    public HouseOrder findHouseOrderById(Long orderId) {
        return houseOrderDAO.selectOne(new QueryWrapper<HouseOrder>().eq(EntityProperty.ID, orderId));
    }

    /**
     * 修改订单状态，和房子租住状态
     *      如果房子是整租，直接修改状态
     *      如果房子是合租，当达到合租房间数，修改状态为已出租
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Integer updateOrderStatusToWaitPay(Long orderId, Integer status) {
        // 查询订单信息
        HouseOrder order = houseOrderDAO.selectOne(new QueryWrapper<HouseOrder>().eq(EntityProperty.ID, orderId));
        // 查询房屋信息
        House house = houseDAO.selectOne(new QueryWrapper<House>().eq(EntityProperty.ID, order.getHouseId()));
        // 修改房屋状态
        if("whole".equals(house.getRentType())){
            // 修改房屋状态
            houseDAO.updateHouseStatus(house.getId(), StatusMsg.houseStatus.HAS_RENT);
            // 修改订单状态
            return houseOrderDAO.updateOrderStatus(orderId, status);
        }else if("share".equals(house.getRentType())){
            // 查询当前房屋已出租数（包含-1-待付款；0-生效中两种状态），注意此处要对租户id做唯一处理
            /*Integer count
                    = houseOrderDAO.selectCount(new QueryWrapper<HouseOrder>()
                    .in("status", new Integer[]{-1, 0})
                    .eq("house_id", house.getId()));*/
            Integer count = houseOrderDAO.findHouseOrderUserNum(house.getId());
            if((count + 1) == house.getBedroomNum()){
                // 修改房屋状态
                houseDAO.updateHouseStatus(house.getId(), StatusMsg.houseStatus.HAS_RENT);
            }
            // 修改订单状态
            return houseOrderDAO.updateOrderStatus(orderId, status);
        }else {     // 其他未知状态
            return -1;
        }
    }

    /**
     * 订单支付成功，修改订单状态，并设置定时任务（在启动类中已设置）
     */
    @Override
    public Integer orderPayed(Long orderId) {
        // 查询订单信息，确定定时任务开启时间
        HouseOrder order = houseOrderDAO.selectOne(new QueryWrapper<HouseOrder>().eq(EntityProperty.ID, orderId));
        if(order == null){
            return -1;
        }
        return houseOrderDAO.updateOrderStatus(orderId, StatusMsg.orderStatus.RENTING);
    }

    /**
     * 查询订单列表，需要区分学生顾客、房东和管理员
     *      并查询订单相关的房子信息、房东信息、顾客信息一起封装
     */
    @Override
    public List<HouseOrder> findOrdersByUser(User user, Page page) {
        // 开启分页
        PageHelper.startPage(page.getCurrent() , page.getLimit());
        // 查询数据
        List<HouseOrder> orders = new ArrayList<>();
        int count = 0;
        if(EntityProperty.userRole.CUSTOMER.equals(user.getRole())){
            orders = houseOrderDAO.selectList(new QueryWrapper<HouseOrder>().eq(EntityProperty.order.CUSTOMER_USER_ID, user.getId()).orderByDesc(EntityProperty.CREATE_TIME));
            count = houseOrderDAO.selectCount(new QueryWrapper<HouseOrder>().eq(EntityProperty.order.CUSTOMER_USER_ID, user.getId()));
        }else if(EntityProperty.userRole.OWNER.equals(user.getRole())){
            orders = houseOrderDAO.selectList(new QueryWrapper<HouseOrder>().eq(EntityProperty.order.OWNER_USER_ID, user.getId()).orderByDesc(EntityProperty.CREATE_TIME));
            count = houseOrderDAO.selectCount(new QueryWrapper<HouseOrder>().eq(EntityProperty.order.OWNER_USER_ID, user.getId()));
        }else if(EntityProperty.userRole.ADMIN.equals(user.getRole())){
            orders = houseOrderDAO.selectList(new QueryWrapper<HouseOrder>().orderByDesc(EntityProperty.CREATE_TIME));
            count = houseOrderDAO.selectCount(new QueryWrapper<HouseOrder>());
        }
        page.setRows(count);
        // 遍历填充房子、用户信息
        if(!orders.isEmpty()){
            for(HouseOrder order : orders){
                // 查询房子信息
                House house = houseDAO.selectOne(new QueryWrapper<House>().eq(EntityProperty.ID, order.getHouseId()));
                order.setHouse(house);
                // 查询房东信息
                User owner = userDAO.selectOne(new QueryWrapper<User>().eq(EntityProperty.ID, order.getOwnerUserId()));
                order.setOwnerUser(owner);
                // 查询顾客信息
                User customer = userDAO.selectOne(new QueryWrapper<User>().eq(EntityProperty.ID, order.getCustomerUserId()));
                order.setCustomerUser(customer);
            }
        }
        return orders;
    }

    /**
     * 修改订单状态，还需要注意房屋出租状态
     */
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Integer updateOrderStatus(Long orderId, Integer orderStatus) {
        /*
            二者都是已出租就修改为未出租的情况，不需要额外再判断：
                如果是整租，则修改状态为未出租
                如果是合租，且状态已经为出租，修改状态为未出租
         */
        HouseOrder order = houseOrderDAO.selectOne(new QueryWrapper<HouseOrder>().eq(EntityProperty.ID, orderId));
        if(order != null){
            House house = houseDAO.selectOne(new QueryWrapper<House>().eq(EntityProperty.ID, order.getHouseId()));
            if(house.getStatus() == StatusMsg.houseStatus.HAS_RENT){
                houseDAO.updateHouseStatus(house.getId(), StatusMsg.houseStatus.UN_RENT);
            }
        }
        return houseOrderDAO.updateOrderStatus(orderId, orderStatus);
    }

    /**
     * 定时任务，查询当前数据库中所有in（-2-待签合同；-1-待付款；0-生效中），将其设置为已过期状态
     *      此外，需要修改房子状态为未出租
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void findAndUpdateExpiredOrder() {
        // 查询数据库中所有已生效的订单
        List<HouseOrder> orders = houseOrderDAO.selectList(new QueryWrapper<HouseOrder>()
                            .eq(EntityProperty.STATUS, new Integer[]{
                                    StatusMsg.orderStatus.RENTING,
                                    StatusMsg.orderStatus.WAIT_PAY,
                                    StatusMsg.orderStatus.WAIT_SIGN}));
        Date now = new Date();
        for(HouseOrder order : orders){
            if(order.getEndDate().before(now)){
                houseOrderDAO.updateOrderStatus(order.getId(), StatusMsg.orderStatus.HAS_EXPIRED);
                House house = houseDAO.selectOne(new QueryWrapper<House>().eq(EntityProperty.ID, order.getHouseId()));
                if("whole".equals(house.getRentType())){
                    houseDAO.updateHouseStatus(house.getId(), StatusMsg.houseStatus.UN_RENT);
                }else if("share".equals(house.getRentType())){
                    // 当前房子有人退租，将房子状态修改为未出租
                    Integer num = houseOrderDAO.findHouseOrderUserNum(order.getHouseId());
                    if(num < house.getLivingRoomNum()){
                        houseDAO.updateHouseStatus(house.getId(), StatusMsg.houseStatus.UN_RENT);
                    }
                }
            }
        }
    }
}
